package parser.persistencia;

import gramatica.Expresion;
import gramatica.Gramatica;
import gramatica.NoTerminal;
import gramatica.Produccion;
import gramatica.Terminal;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import parser.excepciones.ParseoTextoException;

/**
 *
 * @author chevy
 */
public class ParserTexto {
    
    private HashMap<String, Terminal> mapaTerminales;
    private HashMap<String, NoTerminal> mapaNoTerminales;
    private int sigTerm;
    private int sigNoTerm;
    private Scanner scn;
    private int numlinea;
    
    private ParserTexto() {
        this.sigNoTerm = 0;
        this.sigTerm = 0;
        this.numlinea = -1;
        this.mapaNoTerminales = new HashMap<String, NoTerminal>();
        this.mapaTerminales = new HashMap<String, Terminal>();
    }
    
    public static ParserTexto getInstance() {
        return ParserTextoHolder.INSTANCE;
    }
    
    private static class ParserTextoHolder {

        private static final ParserTexto INSTANCE = new ParserTexto();
    }
    
    public Gramatica obtenerGramatica(File archivo) throws ParseoTextoException{
        
        NoTerminal inicio = null;
        HashSet<Terminal> terminales = new HashSet<Terminal>();
        HashSet<NoTerminal> noTerminales = new HashSet<NoTerminal>();
        LinkedList<Produccion> producciones = new LinkedList<Produccion>();
        
        scn = null;
        try {
            scn = new Scanner(archivo);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ParserTexto.class.getName()).log(Level.SEVERE, null, ex);
        }
        while(scn.hasNextLine()){
            this.numlinea++;
            String lineaActual = scn.nextLine();
            if (lineaActual.length() == 0 || lineaActual.charAt(0) == '#')
                continue;

            if(lineaActual.contains("%inicio")){
                inicio = parsearInico(lineaActual);
                noTerminales.add(inicio);
                mapaNoTerminales.put(inicio.getSimb(), inicio);
            }
                    
            else if (lineaActual.contains("%terminal")){
                Terminal term = parsearTerminal(lineaActual);
                terminales.add(term);
                mapaTerminales.put(term.getSimb(), term);
            }
                    
            else if (lineaActual.contains("%noterminal")){
                NoTerminal noterm = parsearNoterminal(lineaActual);
                noTerminales.add(noterm);
                mapaNoTerminales.put(noterm.getSimb(), noterm);
            }
                    
            else if (lineaActual.contains("%produccion")){
                Produccion p = parsearProduccion();
                producciones.add(p);
            }
            else{
                //throw new ParseoTextoException(lineaActual, numlinea, ParseoTextoException.ELEMENTO_GRAMATICAL); 
            }
        }
        Gramatica g = new Gramatica(inicio, producciones, terminales, noTerminales);
        return g;
    }
    
    private NoTerminal parsearInico(String l){
        l.replaceAll("%inicio","");
        l.trim();
        return new NoTerminal(l,sigNoTerm++);
    }
    
    private Terminal parsearTerminal(String l){
        l.replaceAll("%terminal", "");
        l.trim();
        return new Terminal(l, sigTerm++);
    }
    
    private NoTerminal parsearNoterminal(String l){
        l.replaceAll("%noterminal","");
        l.trim();
        return new NoTerminal(l,sigNoTerm++);
    }
    
    private Produccion parsearProduccion(){
        
        NoTerminal izquierda;
        LinkedList<Expresion> derecha;
        String izq = scn.nextLine();
        izq.trim();
        if(this.mapaNoTerminales.containsKey(izq)){
            izquierda = this.mapaNoTerminales.get(izq);
        }
        else{
            throw new ParseoTextoException("") 
        }
        while(scn.findInLine(";").equals(";")){
            String der = s.nextLine();
            der.trim();
            String[] expresiones = der.split(" ");
            for(int i = 0; i<expresiones.length; i++){
                if(this.mapaNoTerminales.containsKey(expresiones[i])){
                    
                }
                else if(this.mapaTerminales.containsKey(expresiones[i])){
                    
                }
                else
                    throw
            }
        }
    }
    
}
